#include "breakpoint.h"

PatchEntry* test_patch_entry;

bool gp_state = false;

uint8_t scan_patch_mod;

void break_point_handler(uint8_t vec_nr){
    struct task_struct* cur_thread = running_thread();
    struct vcpu* vm_thread_cpu = (struct vcpu*)(cur_thread->guest_ptr);
    struct intr_stack* intr_stack;
    intr_stack = (struct intr_stack*)((*((uint32_t*)(0xc0000b0f))) - sizeof(struct intr_stack));

    intr_stack->eip -= 1;
    test_patch_entry = Restore_Patch_Value((uint32_t)(intr_stack->eip));
      
    if (test_patch_entry->patch_addr != 0) {
        if (test_patch_entry->patch_addr == 0x0) {//test
            gp_state = true;
        }
        
        if (gp_state) {
            put_int((uint32_t)(intr_stack->eip));
            put_str("\n");
            put_int((uint32_t)(test_patch_entry->patch_addr));
            put_str("\n");
            asm("jmp .");
        }
        if (test_patch_entry->Value_before_patching == RET) {
            // put_int(intr_stack->eip);
            // put_str("\n");
            intr_stack->eip = (void*)(*((uint32_t*)(intr_stack->esp)));
            intr_stack->esp += 4;
            // put_int(intr_stack->eip);
            // put_str("\n");
            //asm("jmp .");
            x86_scan((void *)intr_stack->eip);
        } else if (test_patch_entry->Value_before_patching == RET_IMM16) {
            intr_stack->eip = (void*)(*((uint32_t*)(intr_stack->esp)));
            intr_stack->esp += 8;
            x86_scan((void *)intr_stack->eip);
        } else if (test_patch_entry->Value_before_patching == CALL_RM32) {
            scan_patch_mod = *((uint32_t*)(intr_stack->eip + 0x1));
            switch ((scan_patch_mod >> 3) & 0x7) {
                case 0x2:
                switch ((scan_patch_mod >> 6) & 0x3) {
                    case 0x3://0xd0
                    intr_stack->esp -= 4;
                    *((uint32_t*)(intr_stack->esp)) = intr_stack->eip + 0x2;
                    intr_stack->eip = (void*)(intr_stack->eax);
                    break;
                    case 0x00:
                    intr_stack->esp -= 4;
                    *((uint32_t*)(intr_stack->esp)) = intr_stack->eip + 0x6;
                    intr_stack->eip = (void*)*((uint32_t*)(*((uint32_t*)(intr_stack->eip + 0x2))));
                    // put_int(intr_stack->eip);
                    // put_str("\n");
                    // asm("jmp .");
                    break;
                }
                break;
            }
            x86_scan((void *)intr_stack->eip);
        }
        else {
            *((uint8_t*)(test_patch_entry->patch_addr)) = test_patch_entry->Value_before_patching;
            x86_scan((void *)test_patch_entry->patch_addr);
            if (test_patch_entry->Value_before_patching == INT3) {
                test_patch_entry->patch_addr = 0x0;
            }

        }
    } else {
        put_str("int3 handler\n");
        asm("jmp .");
    }
}

